#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <l4d_stocks>

#include "macros.sp"
#include "helpers.sp"
#define PLUGIN_VERSION		"1.1.9"


#define STRING_LENGTH		32
static const PILLS_ADRENALINE_SLOT				= 4;


static Handle:MunchTimer[MAXPLAYERS+1]; //if run through, revives the player. gets aborted by button or hurt event
static bool:buttondelay[MAXPLAYERS+1];
static bool:IncapDelay[MAXPLAYERS+1];
static bool:DelayedAdvertise[MAXPLAYERS+1];
static bool:IsMunchingMed[MAXPLAYERS+1]; //lets the hooks find the players they need to check up

static Handle:DelaySetting = INVALID_HANDLE;
static Handle:DurationCVAR = INVALID_HANDLE;
static Handle:sdkRevive = INVALID_HANDLE;

static String:GrabProps[4][STRING_LENGTH+1];


public Plugin:myinfo = 
{
	name = "L4D2 Incapped Meds Munch",
	author = "AtomicStryker",
	description = "You can press USE while incapped to use your pills/arenaline and revive yourself",
	version = PLUGIN_VERSION,
	url = "http://forums.alliedmods.net/showthread.php?t=109655"
}

public OnPluginStart()
{
	PrepSDKCall();
	InitArray();
	
	CreateConVar("l4d2_incappedmedsmunch_version", PLUGIN_VERSION, " Version of L4D2 Incapped Meds Munch on this server ", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_NOTIFY|FCVAR_DONTRECORD);
	
	DelaySetting = CreateConVar("l4d2_incappedmedsmunch_delaytime", "1.5", " How long before an Incapped Survivor can use meds ", FCVAR_PLUGIN|FCVAR_NOTIFY);
	DurationCVAR = CreateConVar("l4d2_incappedmedsmunch_duration", "0.1", " How long do you need for reviving yourself ", FCVAR_PLUGIN|FCVAR_NOTIFY);
	
	AutoExecConfig(true, "l4d2_incappedmedsmunch");
	
	HookEvent("player_incapacitated", Event_Incap);
	
	HookEvent("round_start", Event_RoundChange);
	HookEvent("round_end", Event_RoundChange);
}

static InitArray()
{
	strcopy(GrabProps[0], STRING_LENGTH, "m_tongueOwner");
	strcopy(GrabProps[1], STRING_LENGTH, "m_pounceAttacker");
	strcopy(GrabProps[2], STRING_LENGTH, "m_jockeyAttacker");
	strcopy(GrabProps[3], STRING_LENGTH, "m_pummelAttacker");
}

static PrepSDKCall()
{
	new Handle:config = LoadGameConfigFile("l4d2medsmunch");
	
	if (config == INVALID_HANDLE)
	{
		SetFailState("Cant load medsmunch gamedata file");
	}

	StartPrepSDKCall(SDKCall_Player);
	
	if (!PrepSDKCall_SetFromConf(config, SDKConf_Signature, "CTerrorPlayer_OnRevived"))
	{
		CloseHandle(config);
		SetFailState("Cant find CTerrorPlayer_OnRevived Signature in gamedata file");
	}
	
	CloseHandle(config);
	sdkRevive = EndPrepSDKCall();

	if (sdkRevive == INVALID_HANDLE)
	{
		SetFailState("Cant initialize CTerrorPlayer_OnRevived SDKCall, Signature broken");
	}
}

public Action:OnPlayerRunCmd(client, &buttons, &impulse, Float:vel[3], Float:angles[3], &weapon)
{
	if (buttons & IN_USE && !buttondelay[client] && !IsMunchingMed[client])
	{
		if (GetClientTeam(client)!=TEAM_SURVIVORS) return Plugin_Continue;
		if (!IsPlayerIncapped(client)) return Plugin_Continue;
		if (IncapDelay[client]) return Plugin_Continue;
		
		// Whoever pressed USE must be valid, connected, ingame, Survivor and Incapped
		// a little buttondelay because the cmd fires too fast.
		buttondelay[client] = true;
		CreateTimer(1.0, ResetDelay, client);
		
		// Check for an Infected making love to you first.
		if (IsBeingPwnt(client))
		{
			PrintToChat(client, "\x05Get that Infected off you first.");
			return Plugin_Continue;
		}
		
		// Check for the Survivor Pendant
		if (IsBeingRevived(client))
		{
			PrintToChat(client, "\x05You're being revived already.");
			return Plugin_Continue;
		}
		
		new Meds = GetPlayerWeaponSlot(client, PILLS_ADRENALINE_SLOT);
		if (Meds == -1) // this gets returned if you got no Pillz.
		{
			PrintToChat(client, "\x05You aint got no Meds.");
			return Plugin_Continue;
		}
		else //if you DONT have NO PILLs ... you must have some :P
		{
			//commence ze actions!
			IsMunchingMed[client] = true;
			MunchTimer[client] = CreateTimer(GetConVarFloat(DurationCVAR), MunchFinished, client);
			//SetupProgressBar(client, GetConVarFloat(DurationCVAR));
			
			//PrintToChatAll("\x04%N\x01 is attempting to self revive!", client);
		}
	}		
	
	return Plugin_Continue;
}

public Action:ResetDelay(Handle:timer, any:client)
{
	buttondelay[client] = false;
}

public Action:AdvertisePills(Handle:timer, any:client)
{
	IncapDelay[client] = false;
	DelayedAdvertise[client] = false;
	
	if (client < 1
	|| !IsClientInGame(client)
	|| GetClientTeam(client) != TEAM_SURVIVORS
	|| !IsPlayerIncapped(client))
	{
		return;
	}
	
	if (IsBeingPwnt(client) || IsBeingRevived(client))
	{
		DelayedAdvertise[client] = true;
		return;
	}
	
}


public Action:MunchFinished(Handle:timer, any:client)
{
	IsMunchingMed[client] = false;
	MunchTimer[client] = INVALID_HANDLE;
	
	if (!IsClientInGame(client)) return;
	ReviveClient(client);
}

static ReviveClient(client)
{
	new Meds = GetPlayerWeaponSlot(client, PILLS_ADRENALINE_SLOT);
	if (IsValidEdict(Meds))
	{
		RemoveEdict(Meds);
	}
	
	PrintToChatAllExclude(client, -1, "\x04%N\x01 used his \x04pills/adrenaline\x01 (with \x04USE\x01 button) and revived himself!", client);
	
	SDKCall(sdkRevive, client);
	
	SetEntityMoveType(client, MOVETYPE_WALK);
	//ReviveWorkAround(client);
}

/*
static ReviveWorkAround(client)
{
	new count = GetEntProp(client, Prop_Send, "m_currentReviveCount");
	count++;
	
	CheatCommand(client, "give", "health");
	
	SetEntProp(client, Prop_Send, "m_currentReviveCount", count);
	
	CreateTimer(0.1, SetHP1, client); // set hard health delayed
	SetEntPropFloat(client, Prop_Send, "m_healthBuffer", GetConVarFloat(FindConVar("survivor_revive_health")));
}

public Action:SetHP1(Handle:timer, any:client)
{
	SetEntityHealth(client, 1);
}
*/

static bool:IsBeingPwnt(client)
{
	for (new i = 0; i < sizeof(GrabProps); i++)
	{
		if (IsValidClient(GetEntPropEnt(client, Prop_Send, GrabProps[i])))
		{
			return true;
		}
	}
	
	return false;
}

// *********** EVENT GRUNTWORK ****************

public Event_RoundChange (Handle:event, const String:name[], bool:dontBroadcast)
{
	for (new i=1 ; i<=MaxClients ; i++)
	{
		IsMunchingMed[i] = false;
		
		if (MunchTimer[i] != INVALID_HANDLE)
		{
			KillTimer(MunchTimer[i]);
			MunchTimer[i] = INVALID_HANDLE;
		}
	}
}

public Event_Incap(Handle:event, const String:name[], bool:dontBroadcast)
{
	new client = GetClientOfUserId(GetEventInt(event, "userid"));
	IncapDelay[client] = true;
	CreateTimer(GetConVarFloat(DelaySetting), AdvertisePills, client);
}
